package com.cxyd.modules.wms.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cxyd.common.page.PageData;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ConvertUtils;
import com.cxyd.common.utils.ProcResult;
import com.cxyd.common.utils.Result;
import com.cxyd.modules.api.dto.StockDetailDTO;
import com.cxyd.modules.api.entity.StockDetailEntity;
import com.cxyd.modules.api.report.RestCount;
import com.cxyd.modules.api.report.StockDayRes;
import com.cxyd.modules.security.user.SecurityUser;
import com.cxyd.modules.sys.dto.SysUserDTO;
import com.cxyd.modules.sys.service.SysUserService;
import com.cxyd.modules.wms.dao.*;
import com.cxyd.modules.wms.dto.StockDTO;
import com.cxyd.modules.wms.entity.*;
import com.cxyd.modules.wms.service.AllotRecordService;
import com.cxyd.modules.wms.service.StockService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 库存信息
 *
 * @author g_Cycle gengruyi01@163.com
 * @since 1.0.0 2023-04-27
 */
@Service
public class StockServiceImpl extends CrudServiceImpl<StockDao, StockEntity, StockDTO> implements StockService {

    @Resource
    private SysUserService userService;
    @Resource
    private OrderReelDao orderReelDao;
    @Resource
    private LogCheckDao logCheckDao;
    @Resource
    private LocateDao locateDao;
    @Resource
    private PurchaseDetailDao purchaseDetailDao;
    @Resource
    private StockDayDao stockDayDao;

    @Override
    public PageData<StockDTO> page(Map<String, Object> params) {
        //1.查询库存信息
        final IPage<StockEntity> page = baseDao.selectPage(
                getPage(params, null, true),
                getWrapper(params)
        );
        //2.获取用户列表
        final List<SysUserDTO> userList = userService.getList();
        //3.将creator与updater的username通过id进行绑定
        page.getRecords().forEach(entity -> {
            if (entity.getCreator() != null) {
                entity.setCreatorName(userService.getUsernameById(entity.getCreator(), userList));
            }
            if (entity.getUpdater() != null) {
                entity.setUpdaterName(userService.getUsernameById(entity.getUpdater(), userList));
            }
        });
        return getPageData(page, StockDTO.class);
    }

    @Override
    public QueryWrapper<StockEntity> getWrapper(Map<String, Object> params) {
        //查询条件
        String spuNo = (String) params.get("spuNo");
        String spuName = (String) params.get("spuName");
        String contNo = (String) params.get("contNo");
        String reelId = (String) params.get("reelId");
        String curPosition = (String) params.get("curPosition");
        String positionType = (String) params.get("positionType");
        String stockType = (String) params.get("stockType");

        QueryWrapper<StockEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(positionType), "position_type", positionType);
        wrapper.eq(StringUtils.isNotBlank(stockType), "stock_type", stockType);
        wrapper.like(StringUtils.isNotBlank(contNo), "cont_no", contNo);
        wrapper.like(StringUtils.isNotBlank(reelId), "reel_id", reelId);
        wrapper.like(StringUtils.isNotBlank(spuNo), "spu_no", spuNo);
        wrapper.like(StringUtils.isNotBlank(spuName), "spu_name", spuName);
        wrapper.like(StringUtils.isNotBlank(curPosition), "cur_position", curPosition);

        wrapper.orderByAsc("spu_no");
        wrapper.orderByAsc("unit_name");
        wrapper.orderByAsc("create_date");

        return wrapper;
    }

    @Override
    public List<StockDetailDTO> stockQuery(Map<String, Object> params) {
        List<StockDetailEntity> entityList = baseDao.queryStockList(params);
        return ConvertUtils.sourceToTarget(entityList, StockDetailDTO.class);
    }

    @Override
    public PageData<StockDTO> checkPage(Map<String, Object> params) {
        //获取盘点列表
        IPage<StockEntity> page = baseDao.selectCheckStockList(
                getPage(params, "stock_id", true),
                getWrapper(params));
        //获取分页对象
        return getPageData(page, StockDTO.class);
    }

    @Override
    public ProcResult stockFreeze(List<StockDTO> dtos) {
        //业务逻辑...
//        baseDao.procStockFreeze(params);
//        final String code = (String) params.get("code");
//        final String msg = (String) params.get("msg");
//        return new ProcResult().result(code, msg);
        return new ProcResult();

        //库存已分配就不能冻结了

    }

    @Override
    public ProcResult stockCheck(Map<String, Object> params) {
        String stockId = (String) params.get("stockId");
        String stationNo = (String) params.get("stationNo");
        if (StringUtils.isBlank(stockId)) {
            return new ProcResult().result("123", "未选择待盘点库存");
        }
        if (StringUtils.isBlank(stationNo)) {
            return new ProcResult().result("123", "盘点站台不能为空");
        }
        //业务逻辑...
        baseDao.procStockCheck(params);
        final String code = (String) params.get("code");
        final String msg = (String) params.get("msg");
        return new ProcResult().result(code, msg);
    }

    @Override
    public ProcResult mergeCall(Map<String, Object> params) {
        String stockId = (String) params.get("stockId");
        String stationNo = (String) params.get("stationNo");
        if (StringUtils.isBlank(stockId)) {
            return new ProcResult().result("123", "未选择需合料的托盘");
        }
        if (StringUtils.isBlank(stationNo)) {
            return new ProcResult().result("123", "呼叫站台不能为空");
        }
        baseDao.procMergeCall(params);
        final String code = (String) params.get("code");
        final String msg = (String) params.get("msg");
        return new ProcResult().result(code, msg);
    }

    @Override
    public ProcResult checkAffirm(Map<String, Object> params) {
        String code = "";
        String msg = "";

        try {
            Long stockId = Long.parseLong((String) params.get("stockId"));
            Long actlQty = Long.parseLong((String) params.get("actlQty"));
            BigDecimal actQty = new BigDecimal(actlQty);
            StockEntity stockEntity = baseDao.selectById(stockId);
            String reelId = stockEntity.getReelId();
            Long userId = SecurityUser.getUser().getId();
            Date now = new Date();

            if (orderReelDao.exists(new QueryWrapper<OrderReelEntity>()
                    .eq("reel_id", reelId)
                    .eq("detail_st", 0))) {
                throw new Exception("reelId[" + reelId + "]有出库任务，不允许调整数量");

            }
            if (locateDao.exists(new QueryWrapper<LocateEntity>()
                    .eq("cont_no", stockEntity.getContNo()))) {
                throw new Exception("reelId[" + reelId + "]的料箱【" + stockEntity.getContNo()
                        + "】在庫位上，還未出庫完成");
            }

            if (actlQty < 0) {
                throw new Exception("reelId[" + reelId + "]的盘点数量【" + actlQty
                        + "】小于0");
            } else if (actlQty > 0) {
                //修改库存数量
                StockEntity stockUpdate = new StockEntity();
                stockUpdate.setStockId(stockId);
                stockUpdate.setStockQty(actQty);
                baseDao.updateById(stockUpdate);
            } else {
                //等于0
                //删库存
                baseDao.deleteById(stockEntity);
            }

            //盘点记录
            LogCheckEntity checkLog = new LogCheckEntity();
            checkLog.setReelId(reelId);
            checkLog.setActQty(actQty);
            checkLog.setStockQty(stockEntity.getStockQty());
            checkLog.setSpuNo(stockEntity.getSpuNo());
            checkLog.setContNo(stockEntity.getContNo());
            checkLog.setContLocateNo(stockEntity.getContLocateNo());
            checkLog.setCreateDate(now);
            checkLog.setUpdateDate(now);
            checkLog.setCreator(userId);
            checkLog.setUpdater(userId);
            logCheckDao.insert(checkLog);
            code = "0";
            msg = "reelId[" + reelId + "]調整數量成功";


        } catch (Exception ex) {
            code = "-1";
            msg = ex.toString();

        }

        return new ProcResult().result(code, msg);
    }

    @Override
    public ProcResult deleteReel(Map<String, Object> params) {
        String code = "";
        String msg = "";
        Long userId = SecurityUser.getUser().getId();
        Date now = new Date();
        try {

            String reelId = (String) params.get("reelId");
            String contLocateNo = (String) params.get("contLocateNo");
            if (!baseDao.exists(new QueryWrapper<StockEntity>()
                    .eq("reel_id", reelId)
                    .eq("cont_locate_no", contLocateNo))) {
                throw new Exception("reelid[" + reelId + "]未入庫");
            }
            //更新入庫記錄撤銷
            if (orderReelDao.exists(new QueryWrapper<OrderReelEntity>()
                    .eq("reel_id", reelId)
                    .eq("detail_st", 0))) {
                throw new Exception("reelid[" + reelId + "]需要出庫，不允許刪除");
            }

            List<PurchaseDetailEntity> inDetail = purchaseDetailDao.selectList(
                    new QueryWrapper<PurchaseDetailEntity>()
                            .eq("line_no", reelId)
                            .eq("detail_st", 0)
                            .orderByDesc("create_date")
            );
            if (inDetail.stream().count() > 0) {
                PurchaseDetailEntity updateDetail = inDetail.get(0);
                updateDetail.setDetailSt(9);
                updateDetail.setUpdateDate(now);
                purchaseDetailDao.updateById(updateDetail);
            }

            //刪除庫存

            baseDao.delete(new QueryWrapper<StockEntity>()
                    .eq("reel_id", reelId));


            code = "0";
            msg = "reelId[" + reelId + "]庫存刪除成功";
        } catch (Exception ex) {
            code = "-1";
            msg = ex.toString();
        }
        return new ProcResult().result(code, msg);
    }

    @Override
    public String contLocateGet(String reelId) {
        //如果箱号在货位上就不能登记
        try {

            return baseDao.selectContLocate(reelId);
        } catch (Exception ex) {
            return "reelId[" + reelId + "]未入库";

        }
    }

    @Override
    public List<StockDTO> getList(Map<String, Object> params) {
        //1.查询库存信息
        final List<StockEntity> page = baseDao.selectList(
                getWrapper(params)
        );
        //2.获取用户列表
        final List<SysUserDTO> userList = userService.getList();
        //3.将creator与updater的username通过id进行绑定
        page.forEach(entity -> {
            if (entity.getCreator() != null) {
                entity.setCreatorName(userService.getUsernameById(entity.getCreator(), userList));
            }
            if (entity.getUpdater() != null) {
                entity.setUpdaterName(userService.getUsernameById(entity.getUpdater(), userList));
            }
        });
        return ConvertUtils.sourceToTarget(page, StockDTO.class);
    }

    @Override
    public ProcResult lock(Map<String, Object> params) {
        ProcResult result = new ProcResult();

        try {
            Long userId = SecurityUser.getUser().getId();
            Date now = new Date();
            String lockType = (String) params.get("lockType");//0-解凍 1-凍結
            //
            List<String> strArray = (List<String>) params.get("stockIds");

            List<Long> stockIds = strArray.stream()
                    .map(Long::parseLong)
                    .collect(Collectors.toList());

            //插入order_reel
            //更新库存状态
            //生成任务和WCS任务
            for (Long stockId : stockIds) {
                StockEntity stockUpdate = baseDao.selectById(stockId);
                if (stockUpdate.getStockSt() != 0) {
                    stockUpdate.setComments("庫存已分配，不允許凍結、解凍");

                } else {
                    stockUpdate.setLockSt(Integer.parseInt(lockType));
                }
                stockUpdate.setUpdateDate(now);
                stockUpdate.setUpdater(userId);
                baseDao.updateById(stockUpdate);

            }


            result.setCode("0");
            result.setMsg("操作成功");

        } catch (Exception ex) {
            result.setCode("-1");
            result.setMsg(ex.toString());
        }
        return result;
    }

    @Override
    public StockDayRes getstockDays() {

        StockDayRes result = new StockDayRes();
        result.setTotal(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()));
        result.setNum29(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()
                .le("days", 29)));
        result.setNum59(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()
                .ge("days", 30)
                .le("days", 59)));
        result.setNum89(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()
                .ge("days", 60)
                .le("days", 89)));
        return result;
    }

    @Override
    public StockDayRes getstockDaysDvcNo(String dvcNo) {
        StockDayRes result = new StockDayRes();
        result.setTotal(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()
                .eq("dvc_no",dvcNo)));
        result.setNum29(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()
                .le("days", 29)
                .eq("dvc_no",dvcNo)));
        result.setNum59(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()
                .ge("days", 30)
                .le("days", 59)
                .eq("dvc_no",dvcNo)));
        result.setNum89(stockDayDao.selectCount(new QueryWrapper<StockDayEntity>()
                .ge("days", 60)
                .le("days", 89)
                .eq("dvc_no",dvcNo)));
        return result;
    }

    @Override
    public RestCount getRestCount() {
        RestCount result = new RestCount();
        result.setTotal(baseDao.selectCount(new QueryWrapper<StockEntity>()));
        result.setRest(baseDao.getRestCount());
        return result;
    }
}